;(function () {
  type FunctionType = (...args: any) => any

  // # Parameters  作用：以元组的方式获得函数的入参类型
  type t = Parameters<(name: string, age: number) => any> // [string]

  // !原理
  type Parameters1<T extends FunctionType> = T extends (...args: infer P) => any ? P : never
  /* --------------------------------- */
  // # ReturnType 作用：获得函数返回值的类型

  type t1 = ReturnType<(name: string) => string | number> // string | number
  // !原理
  type ReturnType1<T extends FunctionType> = T extends (...args: any) => infer R ? R : any
  /* --------------------------------- */

  //我们还可以更进一步，比如只匹配第一个参数类型：
  type FirstParameter<T extends FunctionType> = T extends (arg: infer P, ...args: any) => any ? P : never
  type FuncFoo = (arg: number) => void
  type FooFirstParameter = FirstParameter<FuncFoo> // number;

  type FuncBar = (...args: string[]) => void
  type BarFirstParameter = FirstParameter<FuncBar>

  /*------------------------------ */
  //除了对函数类型进行模式匹配，内置工具类型中还有一组对 Class 进行模式匹配的工具类型：
  // # ConstructorParameters 作用：以元组的方式获得构造函数的入参类型(记住:传进去的是类型)
  class test1 {
    name2: string
    constructor(name2: string) {
      this.name2 = name2
    }
  }
  type t_Constructor = ConstructorParameters<(new (name: string) => any) | (new (age: number) => any)>

  // !原理1
  type ConstructorParameters1<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never

  //!原理2
  type ClassType = abstract new (...args: any) => any
  type ConstructorParameters2<T extends ClassType> = T extends abstract new (...args: infer P) => any ? P : never

  type t_Constructor1 = ConstructorParameters1<(new (name: string) => any) | (new (age: number) => any)>
  type t_Constructor2 = ConstructorParameters2<(new (name: string) => any) | (new (age: number) => any)>
  /*------------------------------------------- */
  // # InstanceType 作用：获得构造函数返回值的类型
  type instance_t = InstanceType<new (name: string) => { name: string; age: number }>

  // !原理1
  type InstanceType1<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any

  // !原理2
  type InstanceType2<T extends ClassType> = T extends abstract new (...args: any) => infer R ? R : any

  type ceshi1 = InstanceType1<new (name: string) => { name: string; isBig: boolean }>
  type ceshi2 = InstanceType2<new (name: string) => { name: string; isBig: undefined }>
  /*------------------------------------------- */
})()
//Class 的通用类型签名可能看起来比较奇怪，但实际上它就是声明了可实例化（new）与可抽象（abstract）罢了。我们也可以使用接口来进行声明：
export interface ClassType1<TInstanceType = any> {
  new (...args: any[]): TInstanceType
}

type InstanceType3<T extends ClassType1<string>> = T extends abstract new (...args: any) => infer R ? R : any
type ceshi3 = InstanceType3<new (name: string) => string>
